<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>自定义标题</title>
    <style>
        * {
            box-sizing: border-box;
        }

        html,
        body {
            display: flex;
            flex-direction: column;
            padding: 0;
            margin: 0;
            height: 100%;

            touch-action: manipulation;
        }

        iframe {
            flex: 1;
        }
    </style>
</head>
<body>
<div class="app" style="height: 100vh;width: 100%;"></div>
<script src="https://cdn.bootcss.com/babel-core/5.8.35/browser.min.js"></script>
<script src="https://cdn.bootcss.com/babel-core/5.8.35/browser-polyfill.min.js"></script>
<script src="src/base64.js"></script>
<script src="src/sdk-v0.2.1.js"></script>

<script type="text/babel">
    window.onload = async function() {
        const Bucket = "test-125XXXXXXX";  // 存储桶
        const Region = "ap-guangzhou";  // 地域
        const filePath = "/test.docx";  // 文件路径
        const tokenuid = "test-doc"; // 是否获取Token

        // 根据 Bucket, Region, filePath 拼接文件完整路径
        const objectUrl = `https://${Bucket}.cos.${Region}.myqcloud.com${filePath}`;

        // 定义文档预览请求参数
        const params = {
            copyable: 0,
            htmlwaterword: Base64.encodeUrl('test'),
            htmlfillstyle: Base64.encodeUrl('#006eff'),
            htmlfront: Base64.encodeUrl('bold 10px Serif'),
            htmlrotate: 30,
            htmlhorizontal: 100,
            htmlvertical: 40,
            tokenuid, // 根据传入的tokenuid、文件信息等生成Token，返回Token和有效期；如果不传则不会返回Token信息
        }

        // 步骤1 获取签名sign
        // 传入cos文件路径，服务端计算签名，将签名作为返回结果，格式如下：{code: 0, data: { sign }}
        // 参考服务端示例：https://github.com/tencentyun/cos-demo/tree/main/server/token-refresh-document-preview/nodejs
        const signRes = JSON.parse(await REQUEST('http://127.0.0.1:3000/getSign', 'get', { filePath }));
        // 从返回结果中拿到签名
        const sign = signRes.data.sign || '';

        // 步骤2 通过SDK获取 在线文档预览地址 与 Token信息
        const info = await COSDocPreviewSDK.getPreviewUrlAndToken({
            objectUrl,
            // 如果预览文件是私有的，则需要携带访问凭证
            credentials: {
                authorization: sign,
            },
            ...params,
        })
        const { PreviewUrl, Token, TokenExpireTime } = info;

        // 步骤3 定义refreshToken方法，请求服务端refreshToken接口获取 Token
        const refreshToken = () => {
            return new Promise(function (resolve, reject) {
                console.log('refreshToken：-----------------refresh token', new Date());
                // 传入cos文件地址、tokenuid，服务端会先计算签名，再发起 getObject 请求获取 Token 与 Token过期时间戳，并将其作为返回结果
                // 返回结果格式如下：{code: 0, data: { Token, TokenExpireTime }}
                // 参考服务端示例：https://github.com/tencentyun/cos-demo/tree/main/server/token-refresh-document-preview/nodejs
                const tokenRes = JSON.parse(await REQUEST('http://127.0.0.1:3000/refreshToken', 'get', { Bucket, Region, filePath, tokenuid }));
    
                const TokenExpireTime = tokenRes.data.TokenExpireTime || "";
                // 根据 Token过期时间戳(精确到秒) 计算 Token过期时间(毫秒为单位)
                const timeout = (TokenExpireTime - Math.round(new Date().getTime() / 1000)) * 1000;
    
                const tokenObj = {
                    token: tokenRes.data.Token || "",
                    timeout //设置 Token过期时间
                }
                resolve(tokenObj);
            });
        }

        // 步骤4 初始化预览
        const demo = COSDocPreviewSDK.config({
            mount: document.querySelector('.app'),
            url: PreviewUrl,
            mode: 'normal',
            commonOptions: {
                isShowHeader: false,
                isShowTopArea: false
            },
            refreshToken //将refreshToken作为参数传递
        });

        // 根据 Token过期时间戳(精确到秒) 计算 Token过期时间(毫秒为单位)
        const timeout = (TokenExpireTime - Math.round(new Date().getTime() / 1000)) * 1000;

        // 步骤5 初始传入 Token 与 Token过期时间
        demo.setToken({
            token: Token,
            timeout
        })

        // 步骤6 打开文档
        demo.on('fileOpen', function(data) {
            console.log('打开成功');
            test();
        });

        const test = async () => {
            await demo.ready();
            console.log('demo ready');
        }
    }

    // Promise封装原生XMLHttpRequest，请求参数为请求url、请求方法、请求数据
    const REQUEST = function (url, method, data) {
        return new Promise((resolve, reject) => {
            const xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function() {
                if (xhr.readyState === 4) {
                    if (xhr.status === 200) {
                        resolve(xhr.responseText);
                    } else {
                        reject(new Error("error"));
                    }
                }
            }
            if (method.toUpperCase() === "GET") {
                let paramsList = [];
                for (let key in data) {
                    paramsList.push(key + "=" + data[key]);
                }
                let params = paramsList.join("&");
                url = url + "?" + params;
                xhr.open("get", url, false);
                xhr.send();
            }
            else if (method.toUpperCase() === "POST") {
                xhr.open("post", url, false);
                xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
                xhr.send(data);
            }
        })
    }

</script>
</body>
</html>
